home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / usr / share / pygtk / 2.0 / codegen / codegen.py < prev    next >
Text File  |  2006-01-20  |  52KB  |  1,199 lines

  1. import sys, os, string
  2. import getopt, traceback, keyword
  3. import defsparser, argtypes, override
  4. import definitions
  5. import reversewrapper
  6.  
  7. class Coverage(object):
  8.     def __init__(self, name):
  9.         self.name = name
  10.         self.wrapped = 0
  11.         self.not_wrapped = 0
  12.     def declare_wrapped(self):
  13.         self.wrapped += 1
  14.     def declare_not_wrapped(self):
  15.         self.not_wrapped += 1
  16.     def printstats(self):
  17.         total = (self.wrapped + self.not_wrapped)
  18.         if total:
  19.             print >> sys.stderr, "***INFO*** The coverage of %s is %.2f%% (%i/%i)" %\
  20.                   (self.name, float(self.wrapped*100)/total, self.wrapped, total)
  21.         else:
  22.             print >> sys.stderr, "***INFO*** There are no declared %s." %\
  23.                   (self.name, )
  24.  
  25. functions_coverage = Coverage("global functions")
  26. methods_coverage = Coverage("methods")
  27. vproxies_coverage = Coverage("virtual proxies")
  28. vaccessors_coverage = Coverage("virtual accessors")
  29. iproxies_coverage = Coverage("interface proxies")
  30.  
  31. def exc_info():
  32.     #traceback.print_exc()
  33.     etype, value, tb = sys.exc_info()
  34.     ret = ""
  35.     try:
  36.         sval = str(value)
  37.         if etype == KeyError:
  38.             ret = "No ArgType for %s" % (sval,)
  39.         else:
  40.             ret = sval
  41.     finally:
  42.         del etype, value, tb
  43.     return ret
  44.  
  45. def fixname(name):
  46.     if keyword.iskeyword(name):
  47.     return name + '_'
  48.     return name
  49.  
  50. class FileOutput:
  51.     '''Simple wrapper for file object, that makes writing #line
  52.     statements easier.''' # "
  53.     def __init__(self, fp, filename=None):
  54.         self.fp = fp
  55.         self.lineno = 1
  56.         if filename:
  57.             self.filename = filename
  58.         else:
  59.             self.filename = self.fp.name
  60.     # handle writing to the file, and keep track of the line number ...
  61.     def write(self, str):
  62.         self.fp.write(str)
  63.         self.lineno = self.lineno + string.count(str, '\n')
  64.     def writelines(self, sequence):
  65.         for line in sequence:
  66.             self.write(line)
  67.     def close(self):
  68.         self.fp.close()
  69.     def flush(self):
  70.         self.fp.flush()
  71.  
  72.     def setline(self, linenum, filename):
  73.         '''writes out a #line statement, for use by the C
  74.         preprocessor.''' # "
  75.         self.write('#line %d "%s"\n' % (linenum, filename))
  76.     def resetline(self):
  77.         '''resets line numbering to the original file'''
  78.         self.setline(self.lineno + 1, self.filename)
  79.  
  80. class Wrapper:
  81.     type_tmpl = \
  82.         'PyTypeObject Py%(typename)s_Type = {\n' \
  83.         '    PyObject_HEAD_INIT(NULL)\n' \
  84.         '    0,                    /* ob_size */\n' \
  85.         '    "%(classname)s",            /* tp_name */\n' \
  86.         '    sizeof(%(tp_basicsize)s),            /* tp_basicsize */\n' \
  87.         '    0,                    /* tp_itemsize */\n' \
  88.         '    /* methods */\n' \
  89.         '    (destructor)%(tp_dealloc)s,    /* tp_dealloc */\n' \
  90.         '    (printfunc)0,            /* tp_print */\n' \
  91.         '    (getattrfunc)%(tp_getattr)s,    /* tp_getattr */\n' \
  92.         '    (setattrfunc)%(tp_setattr)s,    /* tp_setattr */\n' \
  93.         '    (cmpfunc)%(tp_compare)s,        /* tp_compare */\n' \
  94.         '    (reprfunc)%(tp_repr)s,        /* tp_repr */\n' \
  95.         '    (PyNumberMethods*)%(tp_as_number)s,     /* tp_as_number */\n' \
  96.         '    (PySequenceMethods*)%(tp_as_sequence)s, /* tp_as_sequence */\n' \
  97.         '    (PyMappingMethods*)%(tp_as_mapping)s,   /* tp_as_mapping */\n' \
  98.         '    (hashfunc)%(tp_hash)s,        /* tp_hash */\n' \
  99.         '    (ternaryfunc)%(tp_call)s,        /* tp_call */\n' \
  100.         '    (reprfunc)%(tp_str)s,        /* tp_str */\n' \
  101.         '    (getattrofunc)%(tp_getattro)s,    /* tp_getattro */\n' \
  102.         '    (setattrofunc)%(tp_setattro)s,    /* tp_setattro */\n' \
  103.         '    (PyBufferProcs*)%(tp_as_buffer)s,    /* tp_as_buffer */\n' \
  104.         '    %(tp_flags)s,                      /* tp_flags */\n' \
  105.         '    NULL,                 /* Documentation string */\n' \
  106.         '    (traverseproc)%(tp_traverse)s,    /* tp_traverse */\n' \
  107.         '    (inquiry)%(tp_clear)s,        /* tp_clear */\n' \
  108.         '    (richcmpfunc)%(tp_richcompare)s,    /* tp_richcompare */\n' \
  109.         '    %(tp_weaklistoffset)s,             /* tp_weaklistoffset */\n' \
  110.         '    (getiterfunc)%(tp_iter)s,        /* tp_iter */\n' \
  111.         '    (iternextfunc)%(tp_iternext)s,    /* tp_iternext */\n' \
  112.         '    %(tp_methods)s,            /* tp_methods */\n' \
  113.         '    0,                    /* tp_members */\n' \
  114.         '    %(tp_getset)s,                   /* tp_getset */\n' \
  115.         '    NULL,                /* tp_base */\n' \
  116.         '    NULL,                /* tp_dict */\n' \
  117.         '    (descrgetfunc)%(tp_descr_get)s,    /* tp_descr_get */\n' \
  118.         '    (descrsetfunc)%(tp_descr_set)s,    /* tp_descr_set */\n' \
  119.         '    %(tp_dictoffset)s,                 /* tp_dictoffset */\n' \
  120.         '    (initproc)%(tp_init)s,        /* tp_init */\n' \
  121.         '    (allocfunc)%(tp_alloc)s,           /* tp_alloc */\n' \
  122.         '    (newfunc)%(tp_new)s,               /* tp_new */\n' \
  123.         '    (freefunc)%(tp_free)s,             /* tp_free */\n' \
  124.         '    (inquiry)%(tp_is_gc)s              /* tp_is_gc */\n' \
  125.         '};\n\n'
  126.  
  127.     slots_list = ['tp_getattr', 'tp_setattr', 'tp_getattro', 'tp_setattro',
  128.                   'tp_compare', 'tp_repr',
  129.                   'tp_as_number', 'tp_as_sequence', 'tp_as_mapping', 'tp_hash',
  130.                   'tp_call', 'tp_str', 'tp_as_buffer', 'tp_richcompare', 'tp_iter',
  131.                   'tp_iternext', 'tp_descr_get', 'tp_descr_set', 'tp_init',
  132.                   'tp_alloc', 'tp_new', 'tp_free', 'tp_is_gc',
  133.                   'tp_traverse', 'tp_clear', 'tp_dealloc', 'tp_flags']
  134.  
  135.     getter_tmpl = \
  136.         'static PyObject *\n' \
  137.         '%(funcname)s(PyObject *self, void *closure)\n' \
  138.         '{\n' \
  139.         '%(varlist)s' \
  140.         '    ret = %(field)s;\n' \
  141.         '%(codeafter)s\n' \
  142.         '}\n\n'
  143.     
  144.     parse_tmpl = \
  145.         '    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "%(typecodes)s:%(name)s"%(parselist)s))\n' \
  146.         '        return %(errorreturn)s;\n'
  147.  
  148.     deprecated_tmpl = \
  149.         '    if (PyErr_Warn(PyExc_DeprecationWarning, "%(deprecationmsg)s") < 0)\n' \
  150.         '        return %(errorreturn)s;\n'
  151.  
  152.     methdef_tmpl = '    { "%(name)s", (PyCFunction)%(cname)s, %(flags)s },\n'
  153.  
  154.     noconstructor = \
  155.         'static int\n' \
  156.         'pygobject_no_constructor(PyObject *self, PyObject *args, PyObject *kwargs)\n' \
  157.         '{\n' \
  158.         '    gchar buf[512];\n' \
  159.         '\n' \
  160.         '    g_snprintf(buf, sizeof(buf), "%s is an abstract widget", self->ob_type->tp_name);\n' \
  161.         '    PyErr_SetString(PyExc_NotImplementedError, buf);\n' \
  162.         '    return -1;\n' \
  163.         '}\n\n'
  164.  
  165.     function_tmpl = \
  166.         'static PyObject *\n' \
  167.         '_wrap_%(cname)s(PyObject *self%(extraparams)s)\n' \
  168.         '{\n' \
  169.         '%(varlist)s' \
  170.         '%(parseargs)s' \
  171.         '%(codebefore)s' \
  172.         '    %(setreturn)s%(cname)s(%(arglist)s);\n' \
  173.         '%(codeafter)s\n' \
  174.         '}\n\n'
  175.  
  176.     virtual_accessor_tmpl = \
  177.         'static PyObject *\n' \
  178.         '_wrap_%(cname)s(PyObject *cls%(extraparams)s)\n' \
  179.         '{\n' \
  180.         '    gpointer klass;\n' \
  181.         '%(varlist)s' \
  182.         '%(parseargs)s' \
  183.         '%(codebefore)s' \
  184.         '    klass = g_type_class_ref(pyg_type_from_object(cls));\n' \
  185.         '    if (%(class_cast_macro)s(klass)->%(virtual)s)\n' \
  186.         '        %(setreturn)s%(class_cast_macro)s(klass)->%(virtual)s(%(arglist)s);\n' \
  187.         '    else {\n' \
  188.         '        PyErr_SetString(PyExc_NotImplementedError, ' \
  189.         '"virtual method %(name)s not implemented");\n' \
  190.         '        g_type_class_unref(klass);\n' \
  191.         '        return NULL;\n' \
  192.         '    }\n' \
  193.         '    g_type_class_unref(klass);\n' \
  194.         '%(codeafter)s\n' \
  195.         '}\n\n'
  196.  
  197.     # template for method calls
  198.     constructor_tmpl = None
  199.     method_tmpl = None
  200.  
  201.     def __init__(self, parser, objinfo, overrides, fp=FileOutput(sys.stdout)):
  202.         self.parser = parser
  203.         self.objinfo = objinfo
  204.         self.overrides = overrides
  205.         self.fp = fp
  206.         
  207.     def get_lower_name(self):
  208.         return string.lower(string.replace(self.objinfo.typecode,
  209.                                            '_TYPE_', '_', 1))
  210.  
  211.     def get_field_accessor(self, fieldname):
  212.         raise NotImplementedError
  213.  
  214.     def get_initial_class_substdict(self): return {}
  215.  
  216.     def get_initial_constructor_substdict(self, constructor):
  217.         return { 'name': '%s.__init__' % self.objinfo.c_name,
  218.                  'errorreturn': '-1' }
  219.     def get_initial_method_substdict(self, method):
  220.         return { 'name': '%s.%s' % (self.objinfo.c_name, method.name) }
  221.  
  222.     def write_class(self):
  223.         self.fp.write('\n/* ----------- ' + self.objinfo.c_name + ' ----------- */\n\n')
  224.         substdict = self.get_initial_class_substdict()
  225.         if not substdict.has_key('tp_flags'):
  226.             substdict['tp_flags'] = 'Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE'
  227.         substdict['typename'] = self.objinfo.c_name
  228.         if self.overrides.modulename:
  229.             substdict['classname'] = '%s.%s' % (self.overrides.modulename,
  230.                                            self.objinfo.name)
  231.         else:
  232.             substdict['classname'] = self.objinfo.name
  233.  
  234.         # Maybe this could be done in a nicer way, but I'll leave it as it is
  235.         # for now: -- Johan
  236.         if not self.overrides.slot_is_overriden('%s.tp_init' % self.objinfo.c_name):
  237.             substdict['tp_init'] = self.write_constructor()
  238.         substdict['tp_methods'] = self.write_methods()
  239.         substdict['tp_getset'] = self.write_getsets()
  240.         
  241.         # handle slots ...
  242.         for slot in self.slots_list:
  243.             
  244.             slotname = '%s.%s' % (self.objinfo.c_name, slot)
  245.             slotfunc = '_wrap_%s_%s' % (self.get_lower_name(), slot)
  246.             if slot[:6] == 'tp_as_':
  247.                 slotfunc = '&' + slotfunc
  248.             if self.overrides.slot_is_overriden(slotname):
  249.                 data = self.overrides.slot_override(slotname)
  250.                 self.write_function(slotname, data)
  251.                 substdict[slot] = slotfunc
  252.             else:
  253.                 if not substdict.has_key(slot):
  254.                     substdict[slot] = '0'
  255.     
  256.         self.fp.write(self.type_tmpl % substdict)
  257.  
  258.         self.write_virtuals()
  259.  
  260.     def write_function_wrapper(self, function_obj, template,
  261.                                handle_return=0, is_method=0, kwargs_needed=0,
  262.                                substdict=None):
  263.         '''This function is the guts of all functions that generate
  264.         wrappers for functions, methods and constructors.'''
  265.         if not substdict: substdict = {}
  266.         
  267.         info = argtypes.WrapperInfo()
  268.  
  269.         substdict.setdefault('errorreturn', 'NULL')
  270.  
  271.         # for methods, we want the leading comma
  272.         if is_method:
  273.             info.arglist.append('')
  274.  
  275.         if function_obj.varargs:
  276.             raise ValueError, "varargs functions not supported"
  277.  
  278.         for param in function_obj.params:
  279.             if param.pdflt and '|' not in info.parsestr:
  280.                 info.add_parselist('|', [], [])
  281.             handler = argtypes.matcher.get(param.ptype)
  282.             handler.write_param(param.ptype, param.pname, param.pdflt,
  283.                                 param.pnull, info)
  284.  
  285.         substdict['setreturn'] = ''
  286.         if handle_return:
  287.             if function_obj.ret not in ('none', None):
  288.                 substdict['setreturn'] = 'ret = '
  289.             handler = argtypes.matcher.get(function_obj.ret)
  290.             handler.write_return(function_obj.ret,
  291.                                  function_obj.caller_owns_return, info)
  292.  
  293.         if function_obj.deprecated != None:
  294.             deprecated = self.deprecated_tmpl % {
  295.                 'deprecationmsg': function_obj.deprecated,
  296.                 'errorreturn': substdict['errorreturn'] }
  297.         else:
  298.             deprecated = ''
  299.  
  300.         # if name isn't set, set it to function_obj.name
  301.         substdict.setdefault('name', function_obj.name)
  302.  
  303.         if self.objinfo:
  304.             substdict['typename'] = self.objinfo.c_name
  305.         substdict.setdefault('cname',  function_obj.c_name)
  306.         substdict['varlist'] = info.get_varlist()
  307.         substdict['typecodes'] = info.parsestr
  308.         substdict['parselist'] = info.get_parselist()
  309.         substdict['arglist'] = info.get_arglist()
  310.         substdict['codebefore'] = deprecated + \
  311.             string.replace(info.get_codebefore(),
  312.             'return NULL', 'return ' + substdict['errorreturn'])
  313.         substdict['codeafter'] = string.replace(info.get_codeafter(),
  314.             'return NULL', 'return ' + substdict['errorreturn'])
  315.  
  316.         if info.parsestr or kwargs_needed:
  317.             substdict['parseargs'] = self.parse_tmpl % substdict
  318.             substdict['extraparams'] = ', PyObject *args, PyObject *kwargs'
  319.             flags = 'METH_VARARGS|METH_KEYWORDS'
  320.  
  321.             # prepend the keyword list to the variable list
  322.             substdict['varlist'] = info.get_kwlist() + substdict['varlist']
  323.         else:
  324.             substdict['parseargs'] = ''
  325.             substdict['extraparams'] = ''
  326.             flags = 'METH_NOARGS'
  327.  
  328.         return template % substdict, flags
  329.  
  330.     def write_constructor(self):
  331.         initfunc = '0'
  332.         constructor = self.parser.find_constructor(self.objinfo,self.overrides)
  333.         if constructor:
  334.             funcname = constructor.c_name
  335.             try:
  336.                 if self.overrides.is_overriden(funcname):
  337.                     data = self.overrides.override(funcname)
  338.                     self.write_function(funcname, data)
  339.                 else:
  340.                     # ok, a hack to determine if we should use new-style constructores :P
  341.                     if getattr(self, 'write_property_based_constructor', None) is not None:
  342.                         if (len(constructor.params) == 0 or
  343.                             isinstance(constructor.params[0], definitions.Property)):
  344.                             # write_property_based_constructor is only
  345.                             # implemented in GObjectWrapper
  346.                             return self.write_property_based_constructor(constructor)
  347.                         else:
  348.                             print >> sys.stderr, "Warning: generating old-style constructor for",\
  349.                                   constructor.c_name
  350.                     # write constructor from template ...
  351.                     code = self.write_function_wrapper(constructor,
  352.                         self.constructor_tmpl,
  353.                         handle_return=0, is_method=0, kwargs_needed=1,
  354.                         substdict=self.get_initial_constructor_substdict(constructor))[0]
  355.                     self.fp.write(code)
  356.                 initfunc = '_wrap_' + funcname
  357.             except:
  358.                 sys.stderr.write('Could not write constructor for %s: %s\n' 
  359.                                  % (self.objinfo.c_name, exc_info()))
  360.                 initfunc = self.write_noconstructor()
  361.         else:
  362.             initfunc = self.write_default_constructor()
  363.         return initfunc
  364.  
  365.     def write_noconstructor(self):
  366.         # this is a hack ...
  367.         if not hasattr(self.overrides, 'no_constructor_written'):
  368.             self.fp.write(self.noconstructor)
  369.             self.overrides.no_constructor_written = 1
  370.         initfunc = 'pygobject_no_constructor'
  371.         return initfunc
  372.  
  373.     def write_default_constructor(self):
  374.         return self.write_noconstructor()
  375.  
  376.     def get_methflags(self, funcname):
  377.         if self.overrides.wants_kwargs(funcname):
  378.             return 'METH_VARARGS|METH_KEYWORDS'
  379.         elif self.overrides.wants_noargs(funcname):
  380.             return 'METH_NOARGS'
  381.         else:
  382.             return 'METH_VARARGS'
  383.  
  384.     def write_function(self, funcname, data):
  385.         lineno, filename = self.overrides.getstartline(funcname)
  386.         self.fp.setline(lineno, filename)
  387.         self.fp.write(data)
  388.         self.fp.resetline()
  389.         self.fp.write('\n\n')
  390.  
  391.     def _get_class_virtual_substdict(self, meth, cname, parent):
  392.         substdict = self.get_initial_method_substdict(meth)
  393.         substdict['virtual'] = substdict['name'].split('.')[1]
  394.         substdict['cname'] = cname
  395.         substdict['class_cast_macro'] = parent.typecode.replace('_TYPE_', '_', 1) + "_CLASS"
  396.         substdict['typecode'] = self.objinfo.typecode
  397.         substdict['cast'] = string.replace(parent.typecode, '_TYPE_', '_', 1)
  398.         return substdict
  399.  
  400.     def write_methods(self):
  401.         methods = []
  402.         klass = self.objinfo.c_name
  403.         # First, get methods from the defs files
  404.         for meth in self.parser.find_methods(self.objinfo):
  405.             method_name = meth.c_name
  406.             if self.overrides.is_ignored(method_name):
  407.                 continue
  408.             try:
  409.                 if self.overrides.is_overriden(method_name):
  410.                     if not self.overrides.is_already_included(method_name):
  411.                         data = self.overrides.override(method_name)
  412.                         self.write_function(method_name, data) 
  413.  
  414.                     methflags = self.get_methflags(method_name)
  415.                 else:
  416.                     # write constructor from template ...
  417.                     code, methflags = self.write_function_wrapper(meth,
  418.                         self.method_tmpl, handle_return=1, is_method=1,
  419.                         substdict=self.get_initial_method_substdict(meth))
  420.                     self.fp.write(code)
  421.                 methods.append(self.methdef_tmpl %
  422.                                { 'name':  fixname(meth.name),
  423.                                  'cname': '_wrap_' + method_name,
  424.                                  'flags': methflags})
  425.                 methods_coverage.declare_wrapped()
  426.             except:
  427.                 methods_coverage.declare_not_wrapped()
  428.                 sys.stderr.write('Could not write method %s.%s: %s\n'
  429.                                 % (klass, meth.name, exc_info()))
  430.  
  431.         # Now try to see if there are any defined in the override
  432.         for method_name in self.overrides.get_defines_for(klass):
  433.             c_name = override.class2cname(klass, method_name)
  434.             if self.overrides.is_already_included(method_name):
  435.                 continue
  436.  
  437.             try:
  438.                 data = self.overrides.define(klass, method_name)
  439.                 self.write_function(method_name, data) 
  440.                 methflags = self.get_methflags(method_name)
  441.  
  442.                 methods.append(self.methdef_tmpl %
  443.                                { 'name':  method_name,
  444.                                  'cname': '_wrap_' + c_name,
  445.                                  'flags': methflags})
  446.                 methods_coverage.declare_wrapped()
  447.             except:
  448.                 methods_coverage.declare_not_wrapped()
  449.                 sys.stderr.write('Could not write method %s.%s: %s\n'
  450.                                 % (klass, meth.name, exc_info()))
  451.  
  452.         # Add GObject virtual method accessors, for chaining to parent
  453.         # virtuals from subclasses
  454.         methods += self.write_virtual_accessors()
  455.             
  456.         if methods:
  457.             methoddefs = '_Py%s_methods' % self.objinfo.c_name
  458.             # write the PyMethodDef structure
  459.             methods.append('    { NULL, NULL, 0 }\n')
  460.             self.fp.write('static PyMethodDef %s[] = {\n' % methoddefs)
  461.             self.fp.write(string.join(methods, ''))
  462.             self.fp.write('};\n\n')
  463.         else:
  464.             methoddefs = 'NULL'
  465.         return methoddefs
  466.  
  467.     def write_virtual_accessors(self):
  468.         klass = self.objinfo.c_name
  469.         methods = []
  470.         for meth in self.parser.find_virtuals(self.objinfo):
  471.             method_name = self.objinfo.c_name + "__do_" + meth.name
  472.             if self.overrides.is_ignored(method_name):
  473.                 continue
  474.             try:
  475.                 if self.overrides.is_overriden(method_name):
  476.                     if not self.overrides.is_already_included(method_name):
  477.                         data = self.overrides.override(method_name)
  478.                         self.write_function(method_name, data)
  479.                     methflags = self.get_methflags(method_name)
  480.                 else:
  481.                     # temporarily add a 'self' parameter as first argument
  482.                     meth.params.insert(0, definitions.Parameter(
  483.                         ptype=(self.objinfo.c_name + '*'),
  484.                         pname='self', pdflt=None, pnull=None))
  485.                     try:
  486.                         # write method from template ...
  487.                         code, methflags = self.write_function_wrapper(meth,
  488.                             self.virtual_accessor_tmpl, handle_return=True, is_method=False,
  489.                             substdict=self._get_class_virtual_substdict(meth, method_name, self.objinfo))
  490.                         self.fp.write(code)
  491.                     finally:
  492.                         del meth.params[0]
  493.                 methods.append(self.methdef_tmpl %
  494.                                { 'name':  "do_" + fixname(meth.name),
  495.                                  'cname': '_wrap_' + method_name,
  496.                                  'flags': methflags + '|METH_CLASS'})
  497.                 vaccessors_coverage.declare_wrapped()
  498.             except:
  499.                 vaccessors_coverage.declare_not_wrapped()
  500.                 sys.stderr.write('Could not write virtual accessor method %s.%s: %s\n'
  501.                                 % (klass, meth.name, exc_info()))
  502.         return methods
  503.  
  504.     def write_virtuals(self):
  505.         '''Write _wrap_FooBar__proxy_do_zbr() reverse wrapers for GObject virtuals'''
  506.         klass = self.objinfo.c_name
  507.         virtuals = []
  508.         for meth in self.parser.find_virtuals(self.objinfo):
  509.             method_name = self.objinfo.c_name + "__proxy_do_" + meth.name
  510.             if self.overrides.is_ignored(method_name):
  511.                 continue
  512.             try:
  513.                 if self.overrides.is_overriden(method_name):
  514.                     if not self.overrides.is_already_included(method_name):
  515.                         data = self.overrides.override(method_name)
  516.                         self.write_function(method_name, data)
  517.                 else:
  518.                     # write virtual proxy ...
  519.                     ret, props = argtypes.matcher.get_reverse_ret(meth.ret)
  520.                     wrapper = reversewrapper.ReverseWrapper(
  521.                         '_wrap_' + method_name, is_static=True)
  522.                     wrapper.set_return_type(ret(wrapper, **props))
  523.                     wrapper.add_parameter(reversewrapper.PyGObjectMethodParam(
  524.                         wrapper, "self", method_name="do_" + meth.name,
  525.                         c_type=(klass + ' *')))
  526.                     for param in meth.params:
  527.                         handler, props = argtypes.matcher.get_reverse(param.ptype)
  528.                         wrapper.add_parameter(handler(wrapper, param.pname, **props))
  529.                     buf = reversewrapper.MemoryCodeSink()
  530.                     wrapper.generate(buf)
  531.                     self.fp.write(buf.flush())
  532.                 virtuals.append((fixname(meth.name), '_wrap_' + method_name))
  533.                 vproxies_coverage.declare_wrapped()
  534.             except KeyError:
  535.                 vproxies_coverage.declare_not_wrapped()
  536.                 virtuals.append((fixname(meth.name), None))
  537.                 sys.stderr.write('Could not write virtual proxy %s.%s: %s\n'
  538.                                 % (klass, meth.name, exc_info()))
  539.         if virtuals:
  540.             # Write a 'pygtk class init' function for this object,
  541.             # except when the object type is explicitly ignored (like
  542.             # GtkPlug and GtkSocket on win32).
  543.             if self.overrides.is_ignored(self.objinfo.typecode):
  544.                 return
  545.             class_cast_macro = self.objinfo.typecode.replace('_TYPE_', '_', 1) + "_CLASS"
  546.             cast_macro = self.objinfo.typecode.replace('_TYPE_', '_', 1)
  547.             funcname = "__%s_class_init" % klass
  548.             self.objinfo.class_init_func = funcname
  549.             have_implemented_virtuals = not not [True for name, cname in virtuals
  550.                                                           if cname is not None]
  551.             self.fp.write(('\nstatic int\n'
  552.                            '%(funcname)s(gpointer gclass, PyTypeObject *pyclass)\n'
  553.                            '{\n') % vars())
  554.  
  555.             if have_implemented_virtuals:
  556.                 self.fp.write('    PyObject *o;\n')
  557.                 self.fp.write(
  558.                     '    %(klass)sClass *klass = %(class_cast_macro)s(gclass);\n'
  559.                     % vars())
  560.                 
  561.             for name, cname in virtuals:
  562.                 do_name = 'do_' + name
  563.                 if cname is None:
  564.                     self.fp.write('\n    /* overriding %(do_name)s '
  565.                                   'is currently not supported */\n' % vars())
  566.                 else:
  567.                     self.fp.write('''
  568.     if ((o = PyDict_GetItemString(pyclass->tp_dict, "%(do_name)s"))
  569.         && !PyObject_TypeCheck(o, &PyCFunction_Type))
  570.         klass->%(name)s = %(cname)s;\n''' % vars())
  571.             self.fp.write('    return 0;\n}\n')
  572.     
  573.     def write_getsets(self):
  574.         lower_name = self.get_lower_name()
  575.         getsets_name = lower_name + '_getsets'
  576.         getterprefix = '_wrap_' + lower_name + '__get_'
  577.         setterprefix = '_wrap_' + lower_name + '__set_'
  578.  
  579.         # no overrides for the whole function.  If no fields, don't write a func
  580.         if not self.objinfo.fields:
  581.             return '0'
  582.         getsets = []
  583.         for ftype, fname in self.objinfo.fields:
  584.             gettername = '0'
  585.             settername = '0'
  586.             attrname = self.objinfo.c_name + '.' + fname
  587.             if self.overrides.attr_is_overriden(attrname): 
  588.                 code = self.overrides.attr_override(attrname)
  589.                 self.write_function(attrname, code)
  590.                 if string.find(code, getterprefix + fname) >= 0:
  591.                     gettername = getterprefix + fname
  592.                 if string.find(code, setterprefix + fname) >= 0:
  593.                     settername = setterprefix + fname
  594.             if gettername == '0':
  595.                 try:
  596.                     funcname = getterprefix + fname
  597.                     info = argtypes.WrapperInfo()
  598.                     handler = argtypes.matcher.get(ftype)
  599.                     # for attributes, we don't own the "return value"
  600.                     handler.write_return(ftype, 0, info)
  601.                     self.fp.write(self.getter_tmpl %
  602.                                   { 'funcname': funcname,
  603.                                     'varlist': info.varlist,
  604.                                     'field': self.get_field_accessor(fname),
  605.                                     'codeafter': info.get_codeafter() })
  606.                     gettername = funcname
  607.                 except:
  608.                     sys.stderr.write("Could not write getter for %s.%s: %s\n"
  609.                                      % (self.objinfo.c_name, fname, exc_info()))
  610.             if gettername != '0' or settername != '0':
  611.                 getsets.append('    { "%s", (getter)%s, (setter)%s },\n' %
  612.                                (fixname(fname), gettername, settername))
  613.  
  614.         if not getsets:
  615.             return '0'
  616.         self.fp.write('static PyGetSetDef %s[] = {\n' % getsets_name)
  617.         for getset in getsets:
  618.             self.fp.write(getset)
  619.         self.fp.write('    { NULL, (getter)0, (setter)0 },\n')
  620.         self.fp.write('};\n\n')
  621.     
  622.         return getsets_name
  623.  
  624.     def write_functions(self, prefix):
  625.         self.fp.write('\n/* ----------- functions ----------- */\n\n')
  626.         functions = []
  627.             
  628.         # First, get methods from the defs files
  629.         for func in self.parser.find_functions():
  630.             funcname = func.c_name
  631.             if self.overrides.is_ignored(funcname):
  632.                 continue
  633.             try:
  634.                 if self.overrides.is_overriden(funcname):
  635.                     data = self.overrides.override(funcname)
  636.                     self.write_function(funcname, data)
  637.  
  638.                     methflags = self.get_methflags(funcname)
  639.                 else:
  640.                     # write constructor from template ...
  641.                     code, methflags = self.write_function_wrapper(func,
  642.                         self.function_tmpl, handle_return=1, is_method=0)
  643.                     self.fp.write(code)
  644.                 functions.append(self.methdef_tmpl %
  645.                                  { 'name':  func.name,
  646.                                    'cname': '_wrap_' + funcname,
  647.                                    'flags': methflags })
  648.                 functions_coverage.declare_wrapped()
  649.             except:
  650.                 functions_coverage.declare_not_wrapped()
  651.                 sys.stderr.write('Could not write function %s: %s\n'
  652.                                  % (func.name, exc_info()))
  653.  
  654.         # Now try to see if there are any defined in the override
  655.         for funcname in self.overrides.get_functions():
  656.             try:
  657.                 data = self.overrides.function(funcname)
  658.                 self.write_function(funcname)
  659.                 methflags = self.get_methflags(funcname)
  660.                 functions.append(self.methdef_tmpl %
  661.                                  { 'name':  funcname,
  662.                                    'cname': '_wrap_' + funcname,
  663.                                    'flags': methflags })
  664.                 functions_coverage.declare_wrapped()
  665.             except:
  666.                 functions_coverage.declare_not_wrapped()
  667.                 sys.stderr.write('Could not write function %s: %s\n'
  668.                                  % (funcname, exc_info()))
  669.                 
  670.         # write the PyMethodDef structure
  671.         functions.append('    { NULL, NULL, 0 }\n')
  672.         
  673.         self.fp.write('PyMethodDef ' + prefix + '_functions[] = {\n')
  674.         self.fp.write(string.join(functions, ''))
  675.         self.fp.write('};\n\n')
  676.  
  677. class GObjectWrapper(Wrapper):
  678.     constructor_tmpl = \
  679.         'static int\n' \
  680.         '_wrap_%(cname)s(PyGObject *self%(extraparams)s)\n' \
  681.         '{\n' \
  682.         '%(varlist)s' \
  683.         '%(parseargs)s' \
  684.         '%(codebefore)s' \
  685.         '    self->obj = (GObject *)%(cname)s(%(arglist)s);\n' \
  686.         '%(codeafter)s\n' \
  687.         '    if (!self->obj) {\n' \
  688.         '        PyErr_SetString(PyExc_RuntimeError, "could not create %(typename)s object");\n' \
  689.         '        return -1;\n' \
  690.         '    }\n' \
  691.         '%(aftercreate)s' \
  692.         '    pygobject_register_wrapper((PyObject *)self);\n' \
  693.         '    return 0;\n' \
  694.         '}\n\n'
  695.     method_tmpl = \
  696.         'static PyObject *\n' \
  697.         '_wrap_%(cname)s(PyGObject *self%(extraparams)s)\n' \
  698.         '{\n' \
  699.         '%(varlist)s' \
  700.         '%(parseargs)s' \
  701.         '%(codebefore)s' \
  702.         '    %(setreturn)s%(cname)s(%(cast)s(self->obj)%(arglist)s);\n' \
  703.         '%(codeafter)s\n' \
  704.         '}\n\n'
  705.  
  706.     def __init__(self, parser, objinfo, overrides, fp=FileOutput(sys.stdout)):
  707.         Wrapper.__init__(self, parser, objinfo, overrides, fp)
  708.         if self.objinfo:
  709.             self.castmacro = string.replace(self.objinfo.typecode,
  710.                                             '_TYPE_', '_', 1)
  711.  
  712.     def get_initial_class_substdict(self):
  713.         return { 'tp_basicsize'      : 'PyGObject',
  714.                  'tp_weaklistoffset' : 'offsetof(PyGObject, weakreflist)',
  715.                  'tp_dictoffset'     : 'offsetof(PyGObject, inst_dict)' }
  716.     
  717.     def get_field_accessor(self, fieldname):
  718.         castmacro = string.replace(self.objinfo.typecode, '_TYPE_', '_', 1)
  719.         return '%s(pygobject_get(self))->%s' % (castmacro, fieldname)
  720.  
  721.     def get_initial_constructor_substdict(self, constructor):
  722.         substdict = Wrapper.get_initial_constructor_substdict(self, constructor)
  723.         if not constructor.caller_owns_return:
  724.             substdict['aftercreate'] = "    g_object_ref(self->obj);\n"
  725.         else:
  726.             substdict['aftercreate'] = ''
  727.         return substdict
  728.  
  729.     def get_initial_method_substdict(self, method):
  730.         substdict = Wrapper.get_initial_method_substdict(self, method)
  731.         substdict['cast'] = string.replace(self.objinfo.typecode, '_TYPE_', '_', 1)
  732.         return substdict
  733.  
  734.     def write_default_constructor(self):
  735.         return '0'
  736.  
  737.     def write_property_based_constructor(self, constructor):
  738.         out = self.fp
  739.         print >> out, "static int"
  740.         print >> out, '_wrap_%s(PyGObject *self, PyObject *args,'\
  741.               ' PyObject *kwargs)\n{' % constructor.c_name
  742.         print >> out, "    GType obj_type = pyg_type_from_object((PyObject *) self);"
  743.  
  744.         def py_str_list_to_c(arg):
  745.             if arg:
  746.                 return "{" + ", ".join(map(lambda s: '"' + s + '"', arg)) + ", NULL }"
  747.             else:
  748.                 return "{ NULL }"
  749.  
  750.         classname = '%s.%s' % (self.overrides.modulename, self.objinfo.name)
  751.  
  752.         if constructor.params:
  753.             mandatory_arguments = [param for param in constructor.params if not param.optional]
  754.             optional_arguments = [param for param in constructor.params if param.optional]
  755.             arg_names = py_str_list_to_c([param.argname for param in
  756.                                           mandatory_arguments + optional_arguments])
  757.             prop_names = py_str_list_to_c([param.pname for param in
  758.                                           mandatory_arguments + optional_arguments])
  759.  
  760.             print >> out, "    GParameter params[%i];" % len(constructor.params)
  761.             print >> out, "    PyObject *parsed_args[%i] = {NULL, };" % len(constructor.params)
  762.             print >> out, "    char *arg_names[] = %s;" % arg_names
  763.             print >> out, "    char *prop_names[] = %s;" % prop_names
  764.             print >> out, "    guint nparams, i;"
  765.             print >> out
  766.             if constructor.deprecated is not None:
  767.                 print >> out, '    if (PyErr_Warn(PyExc_DeprecationWarning, "%s") < 0)' %\
  768.                       constructor.deprecated
  769.                 print >> out, '        return -1;'
  770.                 print >> out
  771.             print >> out, "    if (!PyArg_ParseTupleAndKeywords(args, kwargs, ",
  772.             template = '"'
  773.             if mandatory_arguments:
  774.                 template += "O"*len(mandatory_arguments)
  775.             if optional_arguments:
  776.                 template += "|" + "O"*len(optional_arguments)
  777.             template += ':%s.__init__"' % classname
  778.             print >> out, template, ", arg_names",
  779.             for i in range(len(constructor.params)):
  780.                 print >> out, ", &parsed_args[%i]" % i,
  781.             print >> out, "))"
  782.             print >> out, "        return -1;"
  783.             print >> out
  784.             print >> out, "    memset(params, 0, sizeof(GParameter)*%i);" % len(constructor.params)
  785.             print >> out, "    if (!pyg_parse_constructor_args(obj_type, arg_names, prop_names,"
  786.             print >> out, "                                    params, &nparams, parsed_args))"
  787.             print >> out, "        return -1;"
  788.             print >> out, "    self->obj = g_object_newv(obj_type, nparams, params);"
  789.             print >> out, "    for (i = 0; i < nparams; ++i)"
  790.             print >> out, "        g_value_unset(¶ms[i].value);"
  791.         else:
  792.             print >> out, "    static char* kwlist[] = { NULL };";
  793.             print >> out
  794.             if constructor.deprecated is not None:
  795.                 print >> out, '    if (PyErr_Warn(PyExc_DeprecationWarning, "%s") < 0)' %\
  796.                       constructor.deprecated
  797.                 print >> out, '        return -1;'
  798.                 print >> out
  799.             print >> out, '    if (!PyArg_ParseTupleAndKeywords(args, kwargs, ":%s.__init__", kwlist))' % classname
  800.             print >> out, "        return -1;"
  801.             print >> out
  802.             print >> out, "    self->obj = g_object_newv(obj_type, 0, NULL);"
  803.  
  804.         print >> out, \
  805.               '    if (!self->obj) {\n' \
  806.               '        PyErr_SetString(PyExc_RuntimeError, "could not create %(typename)s object");\n' \
  807.               '        return -1;\n' \
  808.               '    }\n'
  809.  
  810.         if not constructor.caller_owns_return:
  811.             print >> out, "    g_object_ref(self->obj);\n"
  812.  
  813.         print >> out, \
  814.               '    pygobject_register_wrapper((PyObject *)self);\n' \
  815.               '    return 0;\n' \
  816.               '}\n\n' % { 'typename': classname }
  817.         return "_wrap_%s" % constructor.c_name
  818.  
  819.  
  820. class GInterfaceWrapper(GObjectWrapper):
  821.     def get_initial_class_substdict(self):
  822.         return { 'tp_basicsize'      : 'PyObject',
  823.                  'tp_weaklistoffset' : '0',
  824.                  'tp_dictoffset'     : '0'}
  825.  
  826.     def write_constructor(self):
  827.         # interfaces have no constructors ...
  828.         return '0'
  829.     def write_getsets(self):
  830.         # interfaces have no fields ...
  831.         return '0'
  832.  
  833.     def write_virtual_accessors(self):
  834.         ## we don't want the 'chaining' functions for interfaces
  835.         return []
  836.  
  837.     def write_virtuals(self):
  838.         ## Now write reverse method wrappers, which let python code
  839.         ## implement interface methods.
  840.         # First, get methods from the defs files
  841.         klass = self.objinfo.c_name
  842.         proxies = []
  843.         for meth in self.parser.find_virtuals(self.objinfo):
  844.             method_name = self.objinfo.c_name + "__proxy_do_" + meth.name
  845.             if self.overrides.is_ignored(method_name):
  846.                 continue
  847.             try:
  848.                 if self.overrides.is_overriden(method_name):
  849.                     if not self.overrides.is_already_included(method_name):
  850.                         data = self.overrides.override(method_name)
  851.                         self.write_function(method_name, data)
  852.                 else:
  853.                     # write proxy ...
  854.                     ret, props = argtypes.matcher.get_reverse_ret(meth.ret)
  855.                     wrapper = reversewrapper.ReverseWrapper(
  856.                         '_wrap_' + method_name, is_static=True)
  857.                     wrapper.set_return_type(ret(wrapper, **props))
  858.                     wrapper.add_parameter(reversewrapper.PyGObjectMethodParam(
  859.                         wrapper, "self", method_name="do_" + meth.name,
  860.                         c_type=(klass + ' *')))
  861.                     for param in meth.params:
  862.                         handler, props = argtypes.matcher.get_reverse(param.ptype)
  863.                         wrapper.add_parameter(handler(wrapper, param.pname, **props))
  864.                     buf = reversewrapper.MemoryCodeSink()
  865.                     wrapper.generate(buf)
  866.                     self.fp.write(buf.flush())
  867.                 proxies.append((fixname(meth.name), '_wrap_' + method_name))
  868.                 iproxies_coverage.declare_wrapped()
  869.             except KeyError:
  870.                 iproxies_coverage.declare_not_wrapped()
  871.                 proxies.append((fixname(meth.name), None))
  872.                 sys.stderr.write('Could not write interface proxy %s.%s: %s\n'
  873.                                 % (klass, meth.name, exc_info()))
  874.         if proxies:
  875.             ## Write an interface init function for this object
  876.             funcname = "__%s__interface_init" % klass
  877.             vtable = self.objinfo.vtable
  878.             self.fp.write(('\nstatic void\n'
  879.                            '%(funcname)s(%(vtable)s *iface)\n'
  880.                            '{\n') % vars())
  881.             for name, cname in proxies:
  882.                 do_name = 'do_' + name
  883.                 if cname is not None:
  884.                     self.fp.write('    iface->%s = %s;\n' % (name, cname))
  885.             self.fp.write('}\n\n')
  886.             interface_info = "__%s__iinfo" % klass
  887.             self.fp.write('''
  888. static const GInterfaceInfo %s = {
  889.     (GInterfaceInitFunc) %s,
  890.     NULL,
  891.     NULL
  892. };
  893. ''' % (interface_info, funcname))
  894.             self.objinfo.interface_info = interface_info
  895.             
  896.  
  897. class GBoxedWrapper(Wrapper):
  898.     constructor_tmpl = \
  899.         'static int\n' \
  900.         '_wrap_%(cname)s(PyGBoxed *self%(extraparams)s)\n' \
  901.         '{\n' \
  902.         '%(varlist)s' \
  903.         '%(parseargs)s' \
  904.         '%(codebefore)s' \
  905.         '    self->gtype = %(typecode)s;\n' \
  906.         '    self->free_on_dealloc = FALSE;\n' \
  907.         '    self->boxed = %(cname)s(%(arglist)s);\n' \
  908.         '%(codeafter)s\n' \
  909.         '    if (!self->boxed) {\n' \
  910.         '        PyErr_SetString(PyExc_RuntimeError, "could not create %(typename)s object");\n' \
  911.         '        return -1;\n' \
  912.         '    }\n' \
  913.         '    self->free_on_dealloc = TRUE;\n' \
  914.         '    return 0;\n' \
  915.         '}\n\n'
  916.  
  917.     method_tmpl = \
  918.         'static PyObject *\n' \
  919.         '_wrap_%(cname)s(PyObject *self%(extraparams)s)\n' \
  920.         '{\n' \
  921.         '%(varlist)s' \
  922.         '%(parseargs)s' \
  923.         '%(codebefore)s' \
  924.         '    %(setreturn)s%(cname)s(pyg_boxed_get(self, %(typename)s)%(arglist)s);\n' \
  925.         '%(codeafter)s\n' \
  926.         '}\n\n'
  927.  
  928.     def get_initial_class_substdict(self):
  929.         return { 'tp_basicsize'      : 'PyGBoxed',
  930.                  'tp_weaklistoffset' : '0',
  931.                  'tp_dictoffset'     : '0' }
  932.  
  933.     def get_field_accessor(self, fieldname):
  934.         return 'pyg_boxed_get(self, %s)->%s' % (self.objinfo.c_name, fieldname)
  935.  
  936.     def get_initial_constructor_substdict(self, constructor):
  937.         substdict = Wrapper.get_initial_constructor_substdict(self, constructor)
  938.         substdict['typecode'] = self.objinfo.typecode
  939.         return substdict
  940.  
  941. class GPointerWrapper(GBoxedWrapper):
  942.     constructor_tmpl = \
  943.         'static int\n' \
  944.         '_wrap_%(cname)s(PyGPointer *self%(extraparams)s)\n' \
  945.         '{\n' \
  946.         '%(varlist)s' \
  947.         '%(parseargs)s' \
  948.         '%(codebefore)s' \
  949.         '    self->gtype = %(typecode)s;\n' \
  950.         '    self->pointer = %(cname)s(%(arglist)s);\n' \
  951.         '%(codeafter)s\n' \
  952.         '    if (!self->pointer) {\n' \
  953.         '        PyErr_SetString(PyExc_RuntimeError, "could not create %(typename)s object");\n' \
  954.         '        return -1;\n' \
  955.         '    }\n' \
  956.         '    return 0;\n' \
  957.         '}\n\n'
  958.  
  959.     method_tmpl = \
  960.         'static PyObject *\n' \
  961.         '_wrap_%(cname)s(PyObject *self%(extraparams)s)\n' \
  962.         '{\n' \
  963.         '%(varlist)s' \
  964.         '%(parseargs)s' \
  965.         '%(codebefore)s' \
  966.         '    %(setreturn)s%(cname)s(pyg_pointer_get(self, %(typename)s)%(arglist)s);\n' \
  967.         '%(codeafter)s\n' \
  968.         '}\n\n'
  969.  
  970.     def get_initial_class_substdict(self):
  971.         return { 'tp_basicsize'      : 'PyGPointer',
  972.                  'tp_weaklistoffset' : '0',
  973.                  'tp_dictoffset'     : '0' }
  974.  
  975.     def get_field_accessor(self, fieldname):
  976.         return 'pyg_pointer_get(self, %s)->%s' % (self.objinfo.c_name, fieldname)
  977.  
  978.     def get_initial_constructor_substdict(self, constructor):
  979.         substdict = Wrapper.get_initial_constructor_substdict(self, constructor)
  980.         substdict['typecode'] = self.objinfo.typecode
  981.         return substdict
  982.  
  983. def write_headers(data, fp):
  984.     fp.write('/* -- THIS FILE IS GENERATED - DO NOT EDIT */')
  985.     fp.write('/* -*- Mode: C; c-basic-offset: 4 -*- */\n\n')
  986.     fp.write('#include <Python.h>\n\n\n')
  987.     fp.write(data)
  988.     fp.resetline()
  989.     fp.write('\n\n')
  990.     
  991. def write_imports(overrides, fp):
  992.     fp.write('/* ---------- types from other modules ---------- */\n')
  993.     for module, pyname, cname in overrides.get_imports():
  994.         fp.write('static PyTypeObject *_%s;\n' % cname)
  995.         fp.write('#define %s (*_%s)\n' % (cname, cname))
  996.     fp.write('\n\n')
  997.     
  998. def write_type_declarations(parser, fp):
  999.     fp.write('/* ---------- forward type declarations ---------- */\n')
  1000.     for obj in parser.boxes:
  1001.         fp.write('PyTypeObject Py' + obj.c_name + '_Type;\n')
  1002.     for obj in parser.objects:
  1003.         fp.write('PyTypeObject Py' + obj.c_name + '_Type;\n')
  1004.     for interface in parser.interfaces:
  1005.         fp.write('PyTypeObject Py' + interface.c_name + '_Type;\n')
  1006.     fp.write('\n')
  1007.  
  1008. def write_classes(parser, overrides, fp):
  1009.     for klass, items in ((GBoxedWrapper, parser.boxes),
  1010.                          (GPointerWrapper, parser.pointers),
  1011.                          (GObjectWrapper, parser.objects),
  1012.                          (GInterfaceWrapper, parser.interfaces)):
  1013.         for item in items:
  1014.             instance = klass(parser, item, overrides, fp)
  1015.             instance.write_class()
  1016.             fp.write('\n')
  1017.  
  1018. def write_enums(parser, prefix, fp=sys.stdout):
  1019.     if not parser.enums:
  1020.         return
  1021.     fp.write('\n/* ----------- enums and flags ----------- */\n\n')
  1022.     fp.write('void\n' + prefix + '_add_constants(PyObject *module, const gchar *strip_prefix)\n{\n')
  1023.  
  1024.     for enum in parser.enums:
  1025.         if enum.typecode is None:
  1026.             for nick, value in enum.values:
  1027.                 fp.write('    PyModule_AddIntConstant(module, pyg_constant_strip_prefix("%s", strip_prefix), %s);\n'
  1028.                          % (value, value))
  1029.         else:
  1030.             if enum.deftype == 'enum':
  1031.                 fp.write('  pyg_enum_add(module, "%s", strip_prefix, %s);\n' % (enum.name, enum.typecode))
  1032.             else:
  1033.                 fp.write('  pyg_flags_add(module, "%s", strip_prefix, %s);\n' % (enum.name, enum.typecode))
  1034.             
  1035.     fp.write('\n')
  1036.     fp.write('  if (PyErr_Occurred())\n')
  1037.     fp.write('    PyErr_Print();\n') 
  1038.     fp.write('}\n\n')
  1039.  
  1040. def write_extension_init(overrides, prefix, fp): 
  1041.     fp.write('/* initialise stuff extension classes */\n')
  1042.     fp.write('void\n' + prefix + '_register_classes(PyObject *d)\n{\n')
  1043.     imports = overrides.get_imports()[:]
  1044.     if imports:
  1045.         bymod = {}
  1046.         for module, pyname, cname in imports:
  1047.             bymod.setdefault(module, []).append((pyname, cname))
  1048.         fp.write('    PyObject *module;\n\n')
  1049.         for module in bymod:
  1050.             fp.write('    if ((module = PyImport_ImportModule("%s")) != NULL) {\n' % module)
  1051.             fp.write('        PyObject *moddict = PyModule_GetDict(module);\n\n')
  1052.             for pyname, cname in bymod[module]:
  1053.                 fp.write('        _%s = (PyTypeObject *)PyDict_GetItemString(moddict, "%s");\n' % (cname, pyname))
  1054.                 fp.write('        if (_%s == NULL) {\n' % cname)
  1055.                 fp.write('            PyErr_SetString(PyExc_ImportError,\n')
  1056.                 fp.write('                "cannot import name %s from %s");\n'
  1057.                          % (pyname, module))
  1058.                 fp.write('            return;\n')
  1059.                 fp.write('        }\n')
  1060.             fp.write('    } else {\n')
  1061.             fp.write('        PyErr_SetString(PyExc_ImportError,\n')
  1062.             fp.write('            "could not import %s");\n' % module)
  1063.             fp.write('        return;\n')
  1064.             fp.write('    }\n')
  1065.         fp.write('\n')
  1066.     fp.write(overrides.get_init() + '\n')
  1067.     fp.resetline()
  1068.  
  1069. def write_registers(parser, fp):
  1070.     for boxed in parser.boxes:
  1071.         fp.write('    pyg_register_boxed(d, "' + boxed.name +
  1072.                  '", ' + boxed.typecode + ', &Py' + boxed.c_name + '_Type);\n')
  1073.     for pointer in parser.pointers:
  1074.         fp.write('    pyg_register_pointer(d, "' + pointer.name +
  1075.                  '", ' + pointer.typecode + ', &Py' + pointer.c_name + '_Type);\n')
  1076.     for interface in parser.interfaces:
  1077.         fp.write('    pyg_register_interface(d, "' + interface.name +
  1078.                  '", '+ interface.typecode + ', &Py' + interface.c_name +
  1079.                  '_Type);\n')
  1080.         if interface.interface_info is not None:
  1081.             fp.write('    pyg_register_interface_info(%s, &%s);\n' %
  1082.                      (interface.typecode, interface.interface_info))
  1083.  
  1084.     objects = parser.objects[:]
  1085.     pos = 0
  1086.     while pos < len(objects):
  1087.         parent = objects[pos].parent
  1088.         for i in range(pos+1, len(objects)):
  1089.             if objects[i].c_name == parent:
  1090.                 objects.insert(i+1, objects[pos])
  1091.                 del objects[pos]
  1092.                 break
  1093.         else:
  1094.             pos = pos + 1
  1095.     for obj in objects:
  1096.         bases = []
  1097.         if obj.parent != None:
  1098.             bases.append(obj.parent)
  1099.         bases = bases + obj.implements
  1100.         if bases:
  1101.             fp.write('    pygobject_register_class(d, "' + obj.c_name +
  1102.                      '", ' + obj.typecode + ', &Py' + obj.c_name +
  1103.                      '_Type, Py_BuildValue("(' + 'O' * len(bases) + ')", ' +
  1104.                      string.join(map(lambda s: '&Py'+s+'_Type', bases), ', ') +
  1105.                      '));\n')
  1106.         else:
  1107.             fp.write('    pygobject_register_class(d, "' + obj.c_name +
  1108.                      '", ' + obj.typecode + ', &Py' + obj.c_name +
  1109.                      '_Type, NULL);\n')
  1110.         if obj.class_init_func is not None:
  1111.             fp.write('    pyg_register_class_init(%s, %s);\n' %
  1112.                      (obj.typecode, obj.class_init_func))
  1113.     fp.write('}\n')
  1114.  
  1115. def write_source(parser, overrides, prefix, fp=FileOutput(sys.stdout)):
  1116.     write_headers(overrides.get_headers(), fp)
  1117.     write_imports(overrides, fp)
  1118.     write_type_declarations(parser, fp)
  1119.     write_classes(parser, overrides, fp)
  1120.  
  1121.     wrapper = Wrapper(parser, None, overrides, fp)
  1122.     wrapper.write_functions(prefix)
  1123.  
  1124.     write_enums(parser, prefix, fp)
  1125.     write_extension_init(overrides, prefix, fp)
  1126.     write_registers(parser, fp)
  1127.  
  1128. def register_types(parser):
  1129.     for boxed in parser.boxes:
  1130.         argtypes.matcher.register_boxed(boxed.c_name, boxed.typecode)
  1131.     for pointer in parser.pointers:
  1132.         argtypes.matcher.register_pointer(pointer.c_name, pointer.typecode)
  1133.     for obj in parser.objects:
  1134.         argtypes.matcher.register_object(obj.c_name, obj.parent, obj.typecode)
  1135.     for obj in parser.interfaces:
  1136.         argtypes.matcher.register_object(obj.c_name, None, obj.typecode)
  1137.     for enum in parser.enums:
  1138.     if enum.deftype == 'flags':
  1139.         argtypes.matcher.register_flag(enum.c_name, enum.typecode)
  1140.     else:
  1141.         argtypes.matcher.register_enum(enum.c_name, enum.typecode)
  1142.  
  1143. usage = 'usage: codegen.py [-o overridesfile] [-p prefix] defsfile'
  1144. def main(argv):
  1145.     o = override.Overrides()
  1146.     prefix = 'pygtk'
  1147.     outfilename = None
  1148.     errorfilename = None
  1149.     opts, args = getopt.getopt(argv[1:], "o:p:r:t:D:",
  1150.                         ["override=", "prefix=", "register=", "outfilename=",
  1151.                          "load-types=", "errorfilename="])
  1152.     defines = {} # -Dkey[=val] options
  1153.     for opt, arg in opts:
  1154.         if opt in ('-o', '--override'):
  1155.             o = override.Overrides(arg)
  1156.         elif opt in ('-p', '--prefix'):
  1157.             prefix = arg
  1158.         elif opt in ('-r', '--register'):
  1159.         # Warning: user has to make sure all -D options appear before -r
  1160.             p = defsparser.DefsParser(arg, defines)
  1161.             p.startParsing()
  1162.             register_types(p)
  1163.             del p
  1164.         elif opt == '--outfilename':
  1165.             outfilename = arg
  1166.         elif opt == '--errorfilename':
  1167.             errorfilename = arg
  1168.         elif opt in ('-t', '--load-types'):
  1169.             globals = {}
  1170.             execfile(arg, globals)
  1171.     elif opt == '-D':
  1172.         nameval = arg.split('=')
  1173.         try:
  1174.         defines[nameval[0]] = nameval[1]
  1175.         except IndexError:
  1176.         defines[nameval[0]] = None
  1177.     if len(args) < 1:
  1178.         print >> sys.stderr, usage
  1179.         return 1
  1180.     if errorfilename:
  1181.         sys.stderr = open(errorfilename, "w")
  1182.     p = defsparser.DefsParser(args[0], defines)
  1183.     if not outfilename:
  1184.         outfilename = os.path.splitext(args[0])[0] + '.c'
  1185.         
  1186.     p.startParsing()
  1187.     
  1188.     register_types(p)
  1189.     write_source(p, o, prefix, FileOutput(sys.stdout, outfilename))
  1190.  
  1191.     functions_coverage.printstats()
  1192.     methods_coverage.printstats()
  1193.     vproxies_coverage.printstats()
  1194.     vaccessors_coverage.printstats()
  1195.     iproxies_coverage.printstats()
  1196.  
  1197. if __name__ == '__main__':
  1198.     sys.exit(main(sys.argv))
  1199.